/**
 * This software was produced for the U. S. Government
 * under Contract No. FA8721-09-C-0002, and is
 * subject to the Rights in Noncommercial Computer Software
 * and Noncommercial Computer Software Documentation Clause
 * (DFARS) 252.227-7014 (JUN 1995)
 * 
 * (c) 2009 The MITRE Corporation. All Rights Reserved.
 *
 * SPMIF to OPNET Translator
 * Author: ewalters
 * Created: 2:44:10 PM, Aug 9, 2007
 * MITRE Corporation
 */
package com.mitre.spmif2opnet.analysis.ast;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import com.mitre.spmif2opnet.VisitorContext;
import com.mitre.spmif2opnet.analysis.Identifier;

/**
 * Type that represents an S-PMIF compound node
 */
public class CompoundNode extends Node implements Visitee {
	public enum CompoundType {
		COMPOUND_CASE,
		COMPOUND_PARDO,
		COMPOUND_SPLIT,
		COMPOUND_ERROR;
	}
	
	/**
	 * What kind of compound node?
	 */
	private CompoundType _type;

	/*
	 * What are the child nodes of this node?
	 */
	private List<Node>   _children;
	
	/**
	 * Default constructor
	 * @param name node name
	 * @param id node id
	 * @param type what type of node
	 */
	public CompoundNode(String name, String id, CompoundType type) {
		super(name, id, 1.0);
		_type = type;
		_children = new ArrayList<Node>();
	}
	
	/**
	 * Add a child to the compound node
	 * @param n the child
	 */
	public void addChild(Node n) {
		_children.add(n);
	}
	
	/**
	 * Get this node's children
	 * @return the children
	 */
	public List<Node> getChildren() {
		return _children;
	}
	
	/**
	 * Get the compound type
	 * @return the type
	 */
	public CompoundType getType() {
		return _type;
	}

	/**
	 * Visitor acceptor
	 */
	public <T> VisitorContext<T> accept(NodeVisitor<T> v, VisitorContext<T> c) {
		return v.visit(this, c);
	}

	/**
	 * What resources are associated with the node?
	 * @return the resource names
	 */
	public Collection<String> getResources() {
		Collection<String> res = super.getResources();
		if (res.isEmpty() && !_children.isEmpty()) {
			res = _children.get(0).getResources();
		}
		return res;
	}
	
	/**
	 * Get the services that correspond to the resource
	 * Use the children if they are there and our resources are empty.
	 * @param res_name the resource name
	 * @return the units
	 */
	public double getResourceService(String res_name) {
		Double service = null;
		if (_resources.isEmpty() && !_children.isEmpty()) {
			service = new Double(_children.get(0).getResourceService(res_name));
		} else if (!_resources.isEmpty()) {
			service = _resources.get(res_name);
		}
		return (service == null) ? 0.0 : service.doubleValue();
	}

	/**
	 * Copy function
	 * @return the copy
	 */
	public CompoundNode copy() {
		CompoundNode new_n = new CompoundNode(this.getName(), Identifier.newNodeId(this.getId()), _type); 
		new_n.copyResources(this);
		for (Node n : _children) {
			new_n.addChild(n.copy());
		}
		return new_n;
	}
	
	/**
	 * Parse the compound type from a JAXB String
	 * @param name JAXB name
	 * @return our type
	 */
	public static CompoundType fromJAXBString(String name) {
		if (name.equals("SplitNode")) {
			return CompoundType.COMPOUND_SPLIT;
		} else if (name.equals("CaseNode")) {
			return CompoundType.COMPOUND_CASE;
		} else if (name.equals("PardoNode")) {
			return CompoundType.COMPOUND_PARDO;
		}
		return CompoundType.COMPOUND_ERROR;
	}

	/**
	 * Add resources like a regular Node
	 * @param n the node
	 */
	public void addResources(Node n) {
		this.copyResources(n);
	}
}
